#include "byte_stream.hh"

ByteStream::ByteStream( uint64_t capacity ) : capacity_( capacity ) {}

bool Writer::is_closed() const
{
  // Your code here.
  return close_ == true;
}

void Writer::push( std::string data )
{
  // Your code here.
  if ( error_ || is_closed() || data.empty() ) {
    return;
  }

  size_t len = std::min( data.length(), available_capacity() );
  buffer_.append( data.substr( 0, len ) );
  pushed_len_ += len;
  return;
}

void Writer::close()
{
  // Your code here.
  close_ = true;
}

uint64_t Writer::available_capacity() const
{
  // Your code here.
  return capacity_ - pushed_len_ + popped_len_;
}

uint64_t Writer::bytes_pushed() const
{
  // Your code here.
  return pushed_len_;
}

bool Reader::is_finished() const
{
  // Your code here.
  return close_ && buffer_.empty();
}

uint64_t Reader::bytes_popped() const
{
  // Your code here.
  return popped_len_;
}

std::string_view Reader::peek() const
{
  // Your code here.
  return std::string_view { buffer_ };
}

void Reader::pop( uint64_t len )
{
  if ( error_ || len == 0 || buffer_.empty() ) {
    return;
  }

  auto pop_len = std::min( len, static_cast<uint64_t>( buffer_.size() ) );
  buffer_.erase( buffer_.begin(), buffer_.begin() + static_cast<int64_t>( len ) );
  popped_len_ += pop_len;
}

uint64_t Reader::bytes_buffered() const
{
  // Your code here.
  return pushed_len_ - popped_len_;
}
